home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 …SCII & the Runetime Code / ADC Developer CD (1992-07) (''Butch ASCII And The Runtime Code'')_iso / Dev.CD 199207.iso / Development Platforms / Apple II / Essentials / rTutors / part3.5 / rTutor.c next >
Encoding:
C/C++ Source or Header  |  1991-01-16  |  17.0 KB  |  399 lines  |  [TEXT/pdos]

  1. /* PROGRAM rTutor  */
  2. /* (a home-grown tutorial for writing applications using resources */
  3. /* Part 1 - starting up & shutting down the tools from a ToolStartup */
  4. /*          list kept in a resource */
  5. /* Part 2 - add a menu bar that is kept in a resource */
  6. /* Part 3 - add the event loop so that the menus "come alive" and put up a */
  7. /*          window that is defined in the resource fork */
  8. /* Part 3.2 - change "About" box from a simple beep into an Alert Window and */
  9. /*            redo the Rez and MAKE file so that we can avoid re-compiling */
  10. /*            the the parts that haven't changed and also to show off some */
  11. /*            of Rez's special abilities such as including already compiled */
  12. /*            resources from another file and appending Rez's output to an */
  13. /*            already existing resource without wiping out the existing */
  14. /*            resources... */
  15. /* Part 3.3 - tossed out the seperate Rez file that showed how to include */
  16. /*            pre-compiled resources and the "-a" flag.  If you want to know */
  17. /*            how those are done, see Part 3.2's source.  I also tossed the */
  18. /*            controls out of the window and put some icons in the window.  */
  19. /*            Naturally, the icons are stored as resources. I've also */
  20. /*            slipped in a special cursor that's kept as a resource also - */
  21. /*            mainly to show people how to use the current definition of how */
  22. /*            an rCursor should be defined (the bit map for an rCursor is */
  23. /*            done differently from the bitmap for an rIcon). */
  24. /* Part 3.5 - tossed out the custom cursor (it was put in partially just to */
  25. /*            show how to do it).  Added lots of new icons (used in drawing */
  26. /*            the "levels" and two custom resource types.  Big change this */
  27. /*            time around is the "automating" of the icon drawing - in */
  28. /*            Part 3.3, we hard coded a bunch of calls to "DrawIcon" right */
  29. /*            here in the main source code (ugh).  This time, we've changed */
  30. /*            the main source to draw as many icons where ever we want them. */
  31. /*            See the detailed docs for how and why this was done. */
  32.  
  33. #include <types.h>
  34. #include <INTMATH.h>
  35. #include <MEMORY.h>
  36. #include <MISCTOOL.h>
  37. #include <LOCATOR.h>
  38. #include <DESK.H>
  39. #include <QUICKDRAW.h>
  40. #include <EVENT.h>
  41. #include <CONTROL.h>
  42. #include <WINDOW.h>    
  43. #include <MENU.h>    
  44. #include <GSOS.h>
  45. #include <Resources.h>
  46. #include <QDAux.h>      /* added for part 3.3 */
  47.  
  48. #define  kStartStopID    1L    /* used when starting and shutting down tools */
  49.  
  50. /*---------------------- Menus & Menu Bars ---------------------------*/
  51. #define  kMenuBarID      1L   /* resource ID of the menu bar itself */
  52.  
  53.     /* define all the menu id's */
  54. #define  kAppleMenuID   1000  /* resource ID of the Apple menu */
  55. #define  kFileMenuID    2000  /* resource ID of the File menu */
  56. #define  kEditMenuID    3000  /* resource ID of the Edit menu */
  57.  
  58.     /* now, define the menu item id's */
  59. #define   kAboutBoxID   1001  /* resource ID of the About Box menu item */ 
  60.  
  61. #define   kNewItemID    2001  /* resource ID of the New Item in File menu */
  62. #define   kOpenItemID   2002  /* resource ID of the Open item in File menu */ 
  63. #define   kCloseItemID   255  /* the "Close" item */
  64. #define   kSaveItemID   2004  /* the "Save" item */
  65. #define   kSaveAsItemID 2005  /* the "Save As..." item */
  66. #define   kRevertItemID 2006  /* the "Revert to Saved" item */
  67. #define   kPageItemID   2007  /* the "Page Setup..." item */
  68. #define   kPrintItemID  2008  /* the "Print..." item */
  69. #define   kQuitItemID   2009  /* the "Quit" item */
  70.  
  71. #define   kUndoItemID      250  /* the "Undo" item */
  72. #define   kCutItemID       251  /* the "Cut" item */
  73. #define   kCopyItemID      252  /* the "Copy" item */
  74. #define   kPasteItemID     253  /* the "Paste" item */
  75. #define   kClearItemID     254  /* the "Clear" item */
  76. #define   kSelectItemID   3001  /* the "Select All" item */
  77. #define   kShowClipItemID 3002  /* the "Show ClipBoard" item */
  78.  
  79.     /* define the resource ID's for all windows used by this app */
  80. #define myWindowID    2362L  /* window's resource ID = 2362 */
  81.  
  82. /* declare the constants for our TaskMaster event mask */
  83. #define   kMyTaskMask    0x001FFFFFL  /* this mask is for TaskMaster itself */
  84. #define   kMyEventMask    0xFFFF      /* this mask is passed to GetNextEvent */
  85.  
  86. /* define the constant used to represent the icons */
  87. /* lots of new ones added for part 3.5 */
  88. #define kFloorIcon    1   /* ID of the icon used as the "floor" */
  89. #define kPoleIcon     2   /* for the up/down pole */
  90. #define kCoinIcon     3   /* gold coin */
  91. #define kGemIcon      4   /* diamond  */
  92. #define kRockIcon     5   /* rock */
  93. #define kLeftIcon     6   /* man facing left */
  94. #define kRightIcon    7   /* man facing right */
  95. #define kCenterIcon   8   /* man facing forward */
  96. #define kLeft2Icon    9   /* icon for halfway between positions moving left */
  97. #define kRight2Icon  10   /* icon for halfway between positions moving right */
  98. #define kSplatIcon   11   /* icon for player that fell too far */
  99. #define kEraserIcon 255   /* solid white icon for erasing other icons */
  100.  
  101. /* define constants for the new resource types we created */
  102. #define anIconUsedList 0x6002
  103. #define aSpotList      0x6003
  104.  
  105. /* declare the structures for the new resource types so we can use them */
  106. struct Spot
  107. {
  108.     Point   whereItGoes;    /* upper left corner of icon */
  109.     int     theRow;         /* which row it's in */
  110.     int     theColumn;      /* which column it's in */
  111. };
  112. typedef struct Spot Spot, *SpotPtr, **SpotHndl;
  113.  
  114. struct SpotList
  115. {
  116.     int  numInList; /* number of items in the list */
  117.     Spot spotArray[]; /* the array of spots */
  118. };
  119. typedef struct SpotList SpotList, *SpotListPtr, **SpotListHndl;
  120.  
  121. struct IconUsedList
  122. {
  123.     int numInList;  /* number of icons in the list */
  124.     int iconArry[]; /* the array of icons */
  125. };
  126. typedef struct IconUsedList IconUsedList, *IULPtr, **IULHndl;
  127.  
  128. /* declare the global variable that we'll use with TaskMaster */
  129. WmTaskRec    gMyEvent;
  130.  
  131.     
  132. /* declare all of the global variables that we'll be using */    
  133. unsigned   gMyMemID;     /* holds the ID returned by MMStartup */
  134. Ref        gToolListRef; /* list of tools used to start and stop the tools */
  135. Boolean    gPunt;        /* TRUE if it's time to quit the app */
  136. long       gWhichLevel;  /* indicates which "level" player is on */
  137. long       gFacing;      /* ID of icon being used for player */
  138.  
  139.  
  140. /* ------------------------------------------------------------------------ */
  141. /* the following procedure is responsible for putting up the About box */
  142.  
  143. #define kAboutStr    100L /* define the constant for the About box's string */
  144.  
  145. do_show_about()
  146. {    
  147.     /* change the beep into an Alert Window - grab the Alert from a resource */
  148.     word pickedButton;
  149.     pickedButton = AlertWindow(0x0004,   /* alert string is in resource fork */
  150.                                            /* and is a "C" string */
  151.                                NULL,       /* not used right now */
  152.                                kAboutStr); /* resource ID of Alert's string */
  153. }
  154.  
  155.  
  156. /* ------------------------------------------------------------------------ */
  157. /* the following procedure is responsible for quitting the app */
  158.  
  159. do_quit_app()
  160. {
  161.   /* we actually just set the "quit" flag and let the real quitting happen */
  162.   /* in the main event loop.  Later, we would add code here to cope with */
  163.   /* closing all open windows, saving their contents, etc. */
  164.     
  165.     gPunt = TRUE;
  166. }
  167.  
  168.  
  169. /* ------------------------------------------------------------------------ */
  170. /* the following procedure is responsible for dealing with items picked */
  171. /* from the menus by the user */
  172.  
  173. do_menu_events()
  174. {
  175.  
  176.  unsigned int   pickedMenuID; /*ID of menu the user just picked an item from */
  177.  unsigned int   pickedItemID; /* ID of item the user just picked */
  178.  
  179.  /* the hi-word of wmTaskData is the menu ID */
  180.  pickedMenuID = HiWord(gMyEvent.wmTaskData);
  181.  
  182.  /* the lo-word of wmTaskData is the item ID */
  183.  pickedItemID = LoWord(gMyEvent.wmTaskData);
  184.     
  185.     switch(pickedItemID) 
  186.     {
  187.      case kAboutBoxID : do_show_about();    /* show the About box */
  188.                           break;
  189.      case kNewItemID    : break;            /* that's all for this item */
  190.      case kOpenItemID   : break;            /* that's all for this item */
  191.      case kCloseItemID  : break;            /* that's all for this item */
  192.      case kSaveItemID   : break;            /* that's all for this item */
  193.      case kSaveAsItemID : break;            /* that's all for this item */
  194.      case kRevertItemID : break;            /* that's all for this item */
  195.      case kPageItemID   : break;            /* that's all for this item */
  196.      case kPrintItemID  : break;            /* that's all for this item */
  197.      case kQuitItemID   : do_quit_app();    /* sets gPunt to TRUE  */
  198.                           break;
  199.      case kUndoItemID   : break;            /* that's all for this item */
  200.      case kCutItemID    : break;            /* that's all for this item */
  201.      case kCopyItemID   : break;            /* that's all for this item */
  202.      case kPasteItemID  : break;            /* that's all for this item */
  203.      case kClearItemID  : break;            /* that's all for this item */
  204.      case kSelectItemID : break;            /* that's all for this item */
  205.      case kShowClipItemID : break;          /* that's all for this item */
  206.         
  207.      default: ; /* always have a default action in case something goes wrong */
  208.  
  209.     } /* end of the "switch" statement */
  210.  
  211.     /* Turn off the highlighting on the menu the user picked the item from. */
  212.     /* Then return to the main event loop to see what we'll do next. */
  213.     HiliteMenu(FALSE,pickedMenuID);
  214. }
  215.  
  216.  
  217. /* ------------------------------------------------------------------------ */
  218. /* the following procedure installs the menu bar from a resource */
  219.  
  220. do_make_menus()
  221.    MenuBarRecHndl my_mbar_hndl;
  222.    word menu_bar_height; 
  223.   { 
  224.  
  225.    /* the next three calls are ALL required to bring the menu bar in from */
  226.    /* the resource fork AND make it the current system menu bar.  For */
  227.    /* details, see the IIGS Toolbox Reference, under NewMenuBar2  */
  228.   my_mbar_hndl = NewMenuBar2(refIsResource, kMenuBarID, nil); 
  229.   SetSysBar(my_mbar_hndl); 
  230.   SetMenuBar(nil);
  231.  
  232.   /* now, add NDA's, adjust the sizes of the menus, and draw the menu bar */
  233.   /* kAppleMenuID used to be defined as a long and had to be cast to a */
  234.   /* word here.  It's been redefined to be only a word in size, so the */
  235.   /* casting is no longer needed. */
  236.   FixAppleMenu(kAppleMenuID); /* adds NDA's */
  237.   menu_bar_height =  FixMenuBar(); /* adjust the sizes */
  238.   DrawMenuBar();  /* draw the new menu bar and enjoy! */ 
  239.   }
  240. }
  241.  
  242. /* ------------------------------------------------------------------------ */
  243. /* the following procedure is responsible for starting the tools (using the */
  244. /* list in a resource) if the SartupTools call fails, then gPunt will */
  245. /* contain "TRUE", so we can abort the app the global variable for this */
  246. /* app's memory id is acquired here as well. */
  247.  
  248. do_init_rom()
  249. {
  250.     gMyMemID = _ownerid; /* find out our memory id & save it for later */
  251.  
  252.     /* crank 'em up! - make sure that kStartStopID is defined as a long!!! */
  253.     gToolListRef = StartUpTools(gMyMemID,refIsResource,kStartStopID);
  254.     
  255.     if (_toolErr == noError)
  256.       {      /* there was no error, so the app can continue starting up */
  257.         gPunt = FALSE;
  258.         gWhichLevel = 1; /* start player on first level */
  259.       }
  260.     else
  261.       {     /* something went wrong, so set gPunt to indicate the failure */
  262.         gPunt = TRUE;
  263.       }
  264. }
  265.  
  266.  
  267. /* ------------------------------------------------------------------------ */
  268. /* the following procedure draws the contents of the window that we created */
  269. /* from the template in the resource fork.  Any time the window's content */
  270. /* region needs to be redrawn, this routine gets called. */
  271.  
  272. drawMyContents()
  273. {
  274.    /* declare a couple of local variables that we'll need */
  275.         
  276.    QDIconRecordHndl  my_RHndl;       /* handle to icon loaded from rFork */
  277.    long              my_icon_id;     /* resource ID of icon to be used */
  278.    int               loop_counter1;  /* take a guess :-) */
  279.    int               loop_counter2;  /* another easy one */
  280.    int               how_many_icons; /* number of icons in a level */
  281.    long              my_temp;        /* used for misc junk */
  282.    IULHndl           my_IULHndl;     /* handle to list of icons on this lvl */
  283.    SpotListHndl      my_SLHndl;      /* handle to list of spots to draw at */
  284.    SpotListPtr       my_SLPtr;       /* just a spot list */
  285.    int               xLoc;           /* x-axis location for icon drawing */
  286.    int               yLoc;           /* y-axis location for icon drawing */
  287.  
  288.    my_IULHndl = (IULHndl) LoadResource(anIconUsedList,gWhichLevel);
  289.  
  290.    /* find out how many icons on this level */
  291.    how_many_icons = (**my_IULHndl).numInList;
  292.  
  293.    for (loop_counter1 = 0; loop_counter1 < how_many_icons; loop_counter1++)
  294.    {
  295.      my_icon_id = (**my_IULHndl).iconArry[loop_counter1]; /* get ID of icon */
  296.      my_temp = my_icon_id*0x10000 + gWhichLevel;  /* calculate resource ID */
  297.             
  298.      /* load the spot list for this icon */
  299.      my_SLHndl = (SpotListHndl) LoadResource(aSpotList, my_temp);
  300.             
  301.      /* load the icon from the rFork */
  302.      my_RHndl = (QDIconRecordHndl) LoadResource(rIcon, my_icon_id);
  303.             
  304.      /* lock the handle and draw it at all locations in its spot list */
  305.      HLock(my_SLHndl);
  306.      my_SLPtr = *my_SLHndl; /* speed things up by dereferencing only once */
  307.      for (loop_counter2 = 0; loop_counter2 < my_SLPtr->numInList;
  308.                                                   loop_counter2++)
  309.      {
  310.        DrawIcon(*my_RHndl, 0, my_SLPtr->spotArray[loop_counter2].whereItGoes.h,
  311.                              my_SLPtr->spotArray[loop_counter2].whereItGoes.v);
  312.      }; /* end of for loop_counter2 */
  313.      HUnlock(my_SLHndl);
  314.    }; /* end of for loop_counter1 */
  315.         
  316. } /* end of drawMyContents() */
  317.  
  318.  
  319. /* ------------------------------------------------------------------------ */
  320. /* the following procedure creates a window using a template that is kept */
  321. /* in the application's resource fork */
  322.  
  323. do_make_window()
  324. {
  325.     /* since we only have one window and it can't be closed, we won't */
  326.     /* bother to keep the grafPortPtr in a global.  We can always get it */
  327.     /* back by calling FrontWindow().  Later, when we add multiple windows, */
  328.     /* we'll want a better way to keep track of the grafPortPtr to each */
  329.     /* window, but for now I'd like to keep it simple. */
  330.     
  331.  GrafPortPtr    myWndwPtr;
  332.     
  333.  myWndwPtr = NewWindow2(NIL, /* use "default" title string from param block */
  334.                         NIL, /* use "default" refCon from param block */
  335.                         drawMyContents, /* procedure that draws contents */
  336.                         NIL, /* use std def proc for this window */
  337.                         refIsResource,   /* template is in a resource */
  338.                         myWindowID,       /* resource ID of our window */
  339.                         rWindParam1);    /* template is of param type 1 */
  340.  
  341.   SetPort(myWndwPtr); /* set the Graf Port to the newly created window's */
  342. }
  343.  
  344. /* ------------------------------------------------------------------------ */
  345. /* the following procedure is the main event loop. It runs until gPunt is */
  346. /* set to TRUE by the user picking "Quit" from the File menu. */
  347.  
  348. do_main_event()
  349. {
  350.   word  myTaskCode;  /* used to hold the task codes returned by Task Master */
  351.   
  352.  
  353.   /* tell Task Master which events it can do */
  354.   /* we're lazy, so let it handle everything possible! */
  355.   gMyEvent.wmTaskMask = kMyTaskMask;
  356.  
  357.   while(!gPunt)  /* keep calling Task Master until "Quit" has been selected */
  358.   {
  359.     myTaskCode = TaskMaster(kMyEventMask, &gMyEvent);
  360.     switch(myTaskCode) 
  361.       {
  362.         case wInGoAway:
  363.            break;
  364.         case wInSpecial:
  365.         case wInMenuBar:
  366.            do_menu_events();
  367.             break;
  368.         default:  
  369.                         break; /* always have a default */
  370.       }    /* end of the switch statement */        
  371.     } /* end of the "while" */
  372. } /* end of do_main_event */
  373.  
  374.  
  375. /* ------------------------------------------------------------------------ */
  376. /* the following procedure is the main application itself. */
  377. /* don't forget to add the code that will check the message center to see if */
  378. /* this app was launched by clicking on its icon or by clicking on a data */
  379. /* file created by this app.  If the data file was clicked on, then grab its */
  380. /* name out of the message center and open it instead of opening the */
  381. /* untitled window. */
  382.  
  383. main()
  384. {    
  385.     do_init_rom();    /* get my memory id, start the tools, & set gPunt */
  386.     if (gPunt == FALSE)
  387.       {
  388.         do_make_menus();  /* insert the menu bar */
  389.         do_make_window(); /* create a new window from the resource fork */
  390.         InitCursor();     /* this changes the cursor to the "normal" one. */
  391.                           /* It was left as a watch cursor when the tools */
  392.                           /* were started up. */
  393.  
  394.         do_main_event();
  395.       }
  396.     ShutDownTools(refIsHandle,gToolListRef); /* shut down the tools and quit */
  397. } /* end of main program */
  398.